/*  This file is part of -_-.

    -_- is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    -_- is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with -_-.  If not, see <http://www.gnu.org/licenses/>.

    Copyright 2012-2013 Oliver Katz */

#include "assoc.h"
#include "../debug.h"

z_data z_assoc_new()
{
    _z_assoc tmp;
    tmp.content = z_data_init(0, 0);
    memset(tmp.branches, 0, sizeof(tmp.branches));
    return z_data_wrap(&tmp, Z_TYPEID_ASSOC, sizeof(_z_assoc));
}

z_data *_z_assoc_new()
{
    z_data *tmp = (z_data *)malloc(sizeof(z_data));
    *tmp = z_assoc_new();
    return tmp;
}

int z_assoc_del(z_data *a)
{
    Z_WARNING_DATA(a, 1);
    _z_assoc *tmp = (_z_assoc *)z_data_src_get(a);
    Z_WARNING_ASSOC(tmp, 2);

    z_data_release(tmp->content);
    for (int i = 0; i < 256; i++)
    {
        if (tmp->branches[i] != NULL)
        {
            z_data tmp2 = z_data_init(0, sizeof(_z_assoc));
            z_data_src_set(&tmp2, tmp->branches[i]);
            z_assoc_del(&tmp2);
        }
    }
    return z_data_release(*a);
}

z_data *z_assoc_at(z_data *a, z_data *s)
{
    Z_WARNING_DATA(a, NULL);
    Z_WARNING_DATA(s, NULL);

    if (z_string_size(s) == 0)
    {
        _z_assoc *tmp = (_z_assoc *)z_data_src_get(a);
        Z_WARNING_ASSOC(tmp, NULL);
        return &tmp->content;
    }
    else
    {
        _z_assoc *tmp = (_z_assoc *)z_data_src_get(a);
        Z_WARNING_ASSOC(tmp, NULL);
        z_data next = z_data_init(0, sizeof(_z_assoc));
        if (tmp->branches[z_string_at(s, 0)] == NULL)
        {
            z_data tmp2 = z_assoc_new();
            tmp->branches[z_string_at(s, 0)] = (struct _z_assoc *)z_data_src_get(&tmp2);
        }
        z_data_src_set(&next, tmp->branches[z_string_at(s, 0)]);
        z_data buf = z_string_substring(s, 1, z_string_size(s)-1);
        return z_assoc_at(&next, &buf);
    }
}
